package com.onstar.cn.framework.network.http;

import android.os.Build;

import com.onstar.cn.common.error.CommErrorUtils;
import com.onstar.cn.common.exception.HttpException;
import com.onstar.cn.common.exception.OnStarException;
import com.onstar.cn.common.log.LogManager;
import com.onstar.cn.common.util.CommonUtil;
import com.onstar.cn.common.util.Constants;
import com.onstar.cn.common.util.DeviceUtil;
import com.onstar.cn.framework.BuildConfig;
import com.onstar.cn.framework.network.ClientTraceInstance;
import com.onstar.cn.framework.network.entity.RequestEntity;
import com.onstar.cn.framework.network.entity.SSLConnectionFactory;
import com.onstar.cn.framework.utils.ContextInstance;
import com.onstar.cn.framework.utils.ExceptionUtil;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.zip.GZIPInputStream;

public class RequestThread implements Runnable {
	private boolean isCancel = false;
	// Connection time out
	private int timeout = 15 * 1000;
	// Auto connect
	private boolean isRetryConnect = false;
	// 重试次数
	private int retryCount = 3;
	// 请求tag，区分不同Request请求
	private String tag = "";

	private RequestEntity requestEntity;

	private ResponseHandler responseHandler;

	public boolean isCancel() {
		return isCancel;
	}

	public void setCancel(boolean isCancel) {
		this.isCancel = isCancel;
	}

	public RequestThread(RequestEntity requestEntity, ResponseHandler responseHandler) {
		this.requestEntity = requestEntity;
		this.responseHandler = responseHandler;
	}

	public RequestThread(RequestEntity requestEntity) {
		this.requestEntity = requestEntity;
	}

	private LogManager log = LogManager.getInstance();

	@Override
	public void run() {
		try {
			URL requestUrl = new URL(requestEntity.getUrl());
			HttpURLConnection conn=null;
			if(requestEntity.getUrl().contains("https")){
				//忽略证书信任
//				SSLContext sc = SSLContext.getInstance("TLS");
//				sc.init(null, new TrustManager[] { new MytmArray() }, new SecureRandom());
//				HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
//				HttpsURLConnection.setDefaultHostnameVerifier(new MyHostnameVerifier());
//				conn = (HttpsURLConnection) requestUrl.openConnection();
//				conn.setRequestMethod(requestEntity.getMethod());
				//忽略证书信任
//				SSLContext sc = SSLContext.getInstance("TLS");
//				sc.init(null, new TrustManager[] { new MytmArray() }, new SecureRandom());
//				HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
//				HttpsURLConnection.setDefaultHostnameVerifier(new MyHostnameVerifier());
//                conn = (HttpsURLConnection) requestUrl.openConnection();
//                conn.setRequestMethod(requestEntity.getMethod());

//				SSLContext sslcontext = SSLContext.getInstance("TLSv1");
//				sslcontext.init(null,null, null);
//				SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(sslcontext.getSocketFactory());
//				HttpsURLConnection.setDefaultSSLSocketFactory(NoSSLv3Factory);
//				conn = (HttpsURLConnection) requestUrl.openConnection();
//				conn.setRequestMethod(requestEntity.getMethod());

				conn = SSLConnectionFactory.createStrictSSLConnection(ContextInstance.getInstance().getAppContext(),requestEntity);
//				conn = SSLConnectionFactory.createCommonSSLConnection(requestEntity);

			}else{
				conn = (HttpURLConnection) requestUrl.openConnection();
				conn.setRequestMethod(requestEntity.getMethod());
			}
			conn.setConnectTimeout(timeout > 0 ? timeout : 15 * 1000);
			conn.setReadTimeout(timeout > 0 ? timeout : 15 * 1000);

//			if (!CommonUtil.isNull(requestEntity.getAccept())) {
				conn.addRequestProperty("Accept", requestEntity.getAccept());
//			}

			if (!CommonUtil.isNull(requestEntity.getAccept())) {
				conn.addRequestProperty("Content-Type", requestEntity.getAccept()+";charset=utf-8");
			}
			if (!CommonUtil.isNull(requestEntity.getLanguage())) {
				conn.addRequestProperty("Accept-Language", requestEntity.getLanguage());
			}
			conn.addRequestProperty(Constants.CLIENT_TRACE_ID, ClientTraceInstance.getInstance().getClientTraceId());

			/**
			 * 需要统一加入head的client-info
			 */
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.append("ANDROID");
			stringBuilder.append("_");
			stringBuilder.append(Build.VERSION.RELEASE);
			stringBuilder.append("_");
			stringBuilder.append(BuildConfig.VERSION_CODE);
			stringBuilder.append("_");
			if (DeviceUtil.getLanguage() != null && DeviceUtil.getCountry() != null) {
				stringBuilder.append(DeviceUtil.getLanguage() + "-" + DeviceUtil.getCountry().toUpperCase());
			} else {
				stringBuilder.append("zh-CN");
			}
			stringBuilder.append("_");
			stringBuilder.append(DeviceUtil.getDeviceType());
			stringBuilder.append("_");
			stringBuilder.append(Constants.CLIENT_INFO_SECRET_ID);
			log.d("client info ------------>" + stringBuilder.toString());
			conn.addRequestProperty("CLIENT-INFO", stringBuilder.toString());

			if (!CommonUtil.isNull(requestEntity.getCustomHeads())) {
				Set<Entry<String, Object>> set = requestEntity.getCustomHeads().entrySet();
				Iterator<Entry<String, Object>> it = set.iterator();
				while (it.hasNext()) {
					Entry<String, Object> entry = it.next();
					if (!CommonUtil.isNull(conn.getRequestProperty(entry.getKey()))) {
						conn.setRequestProperty(entry.getKey(), entry.getValue() + "");
					} else {
						conn.addRequestProperty(entry.getKey(), entry.getValue() + "");
					}
				}
			}
			if(!CommonUtil.isNull(requestEntity.getUrl())&&(requestEntity.getUrl().contains("mag")||requestEntity.getUrl().contains("msp"))){
				//需要设置Default Authorization，否则接口无法调用
				conn.addRequestProperty("Authorization", !CommonUtil.isNull(requestEntity.getAuthorization())?requestEntity.getAuthorization():"Authorization");
			}else{
				if(!CommonUtil.isNull(requestEntity.getAuthorization())){
					conn.addRequestProperty("Authorization",requestEntity.getAuthorization() );
				}
			}

			if (!CommonUtil.isNull(requestEntity.getBody())) {
				conn.setDoOutput(true);
				OutputStream output = conn.getOutputStream();
				log.d(getInterfaceName()+",request body------------>" + requestEntity.getBody());
				output.write(requestEntity.getBody().getBytes());
				output.close();
			}

			if (responseHandler != null) {
				// 202 NA doc
				if (conn.getResponseCode() != 200 && conn.getResponseCode() != 202) {
					InputStream is = conn.getErrorStream();

					String encodingHeader = conn.getHeaderField("Content-Encoding");
					if (encodingHeader != null && encodingHeader.toLowerCase().contains("gzip"))
					{
						is = new GZIPInputStream(is);
					}

					BufferedReader br = new BufferedReader(new InputStreamReader(is));
					String line = null;
					StringBuilder sb = new StringBuilder();
					while ((line = br.readLine()) != null) {
						sb.append(line);
					}
					log.i(getInterfaceName()+",failure response ------------>" + sb + conn.getResponseCode());
					CommErrorUtils entity = CommErrorUtils.parseResponse(sb.toString());
					if(entity!=null) {
						responseHandler.onError(tag, new HttpException(entity.getErrorCode(), entity.getErrorMsg()),
								isCancel);
					}else{
						responseHandler.onError(tag, new HttpException("", ""),
								isCancel);
					}
					br.close();
					is.close();
					conn.disconnect();
				} else {
					InputStream is = conn.getInputStream();

					String encodingHeader = conn.getHeaderField("Content-Encoding");
					if (encodingHeader != null && encodingHeader.toLowerCase().contains("gzip"))
					{
						is = new GZIPInputStream(is);
					}

					BufferedReader br = new BufferedReader(new InputStreamReader(is));
					String line = null;
					StringBuilder sb = new StringBuilder();
					while ((line = br.readLine()) != null) {
						sb.append(line);
					}
					log.i(getInterfaceName()+",success response ------------>" + sb);
					responseHandler.onSuccess(tag, sb.toString(), isCancel);
					br.close();
					is.close();
					conn.disconnect();
				}
			}
			conn.disconnect();
		} catch (java.net.SocketTimeoutException e) {
			log.e(e.getMessage());
			if (responseHandler != null) {
				responseHandler.onError(tag, ExceptionUtil.toHttpException(e));
			}
		} catch (MalformedURLException e) {
			log.e(e.getMessage());
			if (responseHandler != null) {
				responseHandler.onError(tag, ExceptionUtil.toHttpException(e));
			}
		} catch (IOException e1) {
			log.e(e1.getMessage());
			if (isRetryConnect) {
				run();
				retryCount--;
				if (retryCount <= 1) {
					isRetryConnect = false;
					retryCount = 3;
				}
			} else {
				if (responseHandler != null) {
					//
					if(!CommonUtil.isNull(e1.getMessage())&&e1.getMessage().contains("No authentication")){
						OnStarException e;
						if(getInterfaceName().equals("upgrade")) {
							e=new OnStarException("L7_invalid_user_credentials_number_dummy","L7_invalid_user_credentials_number_dummy");
						}else {
							e=new OnStarException("L7_invalid_user_credentials_dummy","L7_invalid_user_credentials_dummy");
						}
						responseHandler.onError(tag, ExceptionUtil.toOnStarException(e.getErrorCode(), e.getMessage()), isCancel);
					}else{
						responseHandler.onError(tag, ExceptionUtil.toHttpException(e1), isCancel);
					}
				}
			}
		} catch (Exception e) {
			log.e(e.getMessage());
			if (isRetryConnect) {
				run();
				retryCount--;
				if (retryCount <= 1) {
					isRetryConnect = false;
					retryCount = 3;
				}
			} else {
				if (responseHandler != null) {
					responseHandler.onError(tag, ExceptionUtil.toHttpException(e), isCancel);
				}
			}
		}
	}

	public int getTimeout() {
		return timeout;
	}

	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}

	public boolean isRetryConnect() {
		return isRetryConnect;
	}

	public void setRetryConnect(boolean isRetryConnect) {
		this.isRetryConnect = isRetryConnect;
	}

	public int getRetryCount() {
		return retryCount;
	}

	public void setRetryCount(int retryCount) {
		this.retryCount = retryCount;
	}

	public String getTag() {
		return tag;
	}

	public void setTag(String tag) {
		this.tag = tag;
	}

	public String getInterfaceName(){
		String name="";
		if(!CommonUtil.isNull(requestEntity)&&!CommonUtil.isNull(requestEntity.getUrl())){
			if(requestEntity.getUrl().contains("/")&&requestEntity.getUrl().contains("?")){
				name=requestEntity.getUrl().substring(requestEntity.getUrl().lastIndexOf("/")+1,requestEntity.getUrl().indexOf("?"));
			}else if(requestEntity.getUrl().contains("/")&&!requestEntity.getUrl().contains("?")){
				name=requestEntity.getUrl().substring(requestEntity.getUrl().lastIndexOf("/")+1,requestEntity.getUrl().length());
			}else{
				name="";
			}
		}
		log.d("interface name:"+name);
		return name;
	}
//	private class MyHostnameVerifier implements HostnameVerifier {
//
//		@Override
//		public boolean verify(String hostname, SSLSession session) {
//			return true;
//		}
//	}
//
//	/**
//	 *
//	 * 信任所有主机-对于任何证书都不做检查
//	 *
//	 * @author 7828wc
//	 *
//	 */
//	class MytmArray implements X509TrustManager {
//		public X509Certificate[] getAcceptedIssuers() {
//			// return null;
//			return new X509Certificate[] {};
//		}
//
//		@Override
//		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//
//		}
//
//		@Override
//		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//		}
//	};
}
